/**
 * @param {number[][]} matrix
 * @return {number[]}
 */
export var spiralOrder = function (matrix) {
  const [m, n] = [matrix.length, matrix[0].length]
  const [ans, visited] = [
    new Array(m * n).fill(0),
    new Array(m).fill(0).map(() => new Array(n).fill(false)),
  ]

  const derection = [
    [0, 1],
    [1, 0],
    [0, -1],
    [-1, 0],
  ]
  let [drtIndex, row, col] = [0, 0, 0]

  for (let i = 0; i < ans.length; i++) {
    ans[i] = matrix[row][col]
    visited[row][col] = true
    let [nextRow, nextCol] = [row + derection[drtIndex][0], col + derection[drtIndex][1]]
    if (nextRow < 0 || nextRow >= m || nextCol < 0 || nextCol >= n || visited[nextRow][nextCol]) {
      drtIndex = (drtIndex + 1) % 4
      nextRow = row + derection[drtIndex][0]
      nextCol = col + derection[drtIndex][1]
    }
    ;[row, col] = [nextRow, nextCol]
  }
  return ans
}

/**
 * 收小边界的方法
 * @param {number[][]} matrix
 * @return {number[]}
 */
export var spiralOrder2 = function (matrix) {
  if (matrix.length === 0) {
    return []
  }
  const m = matrix.length
  const n = matrix[0].length

  const res = []

  let lbound = 0
  let rbound = n - 1
  let tbound = 0
  let bbound = m - 1

  let i = 0
  let j = 0

  // 判断方向
  let d = n === 1 ? 'b' : 'r'

  for (let a = 0; a < m * n; a++) {
    res.push(matrix[i][j])
    if (d === 'r') {
      j++
      if (j === rbound) {
        d = 'b'
        tbound++
      }
    } else if (d === 'b') {
      i++
      if (i === bbound) {
        d = 'l'
        rbound--
      }
    } else if (d === 'l') {
      j--
      if (j === lbound) {
        d = 't'
        bbound--
      }
    } else if (d === 't') {
      i--
      if (i === tbound) {
        d = 'r'
        lbound++
      }
    }
  }
  return res
}
